﻿#pragma once

namespace ui {
	enum ONLINE_QUERY_STATE {
		ONLINE_QUERY_STATE_NONE = 0x0000,
		ONLINE_QUERY_STATE_PRE = 0x0001,			//在timer队列, 并未正在请求
		ONLINE_QUERY_STATE_SEND = 0x0002,			//发送了请求
		ONLINE_QUERY_STATE_FINISH,					//完成, 收到了响应
		ONLINE_QUERY_STATE_ERROR,					//完成, 收到了响应
	};

	template<typename _T>
	class UILIB_API UiOnlineQueryObserver {
	public:
		virtual void SetOnlineQueryState(ONLINE_QUERY_STATE state) = 0;
		virtual bool SetOnlineQueryResult(const _T& vec, bool succ = true, std::string err = "") = 0;
	};

	typedef UiOnlineQueryObserver<std::vector<ui::kvItem>> ComboOnlineQueryObserver;

	template<typename _T>
	class UILIB_API UiOnlineQuery : nbase::SupportWeakCallback {
	public:
		UiOnlineQuery() :m_weakOnlineQuery() {};
		virtual ~UiOnlineQuery() {};

		void SetOnlineQueryTimespan(int timespan) { m_clockSpan = timespan; };
		void SetOnlineQueryObserver(UiOnlineQueryObserver<_T>* observer) {
			assert(!m_observer || !observer);
			m_observer = observer;
		};
		void SetOnlineQueryState(ONLINE_QUERY_STATE state) {
			if (m_state != state)
			{
				m_state = state;
				if (m_observer)
					m_observer->SetOnlineQueryState(m_state);
			}
		};

		virtual bool PostOnlineQueryRequest(std::wstring sQuery) {
			m_weakOnlineQuery.Cancel();
			wprintf(L"TimerManager::GetInstance()->AddCancelableTimer %s\n", sQuery.c_str());
			const TIMERINFO::TimerCallback& callback = nbase::Bind(&UiOnlineQuery<_T>::OnlineQueryTimerCallback, this, sQuery);
			TimerManager::GetInstance()->AddCancelableTimer(m_weakOnlineQuery.GetWeakFlag(), callback, 100, TimerManager::REPEAT_FOREVER);
			m_clockPreStart = clock();
			SetOnlineQueryState(ONLINE_QUERY_STATE::ONLINE_QUERY_STATE_PRE);
			return true;
		};
		virtual bool CancelOnlineQueryRequest() {
			m_weakOnlineQuery.Cancel();
			return true;
		};

		virtual void ExtractOnlineQueryResult(const _T& result)
		{
			if (!m_observer) {
				SetOnlineQueryState(ONLINE_QUERY_STATE::ONLINE_QUERY_STATE_ERROR);
				return;
			}

			if (m_observer->SetOnlineQueryResult(result)) {
				SetOnlineQueryState(ONLINE_QUERY_STATE::ONLINE_QUERY_STATE_FINISH);
			}
			else
				SetOnlineQueryState(ONLINE_QUERY_STATE::ONLINE_QUERY_STATE_ERROR);
		}

		void OnlineQueryTimerCallback(std::wstring sQuery) {
			wprintf(L"UiOnlineQuery::OnlineQueryTimerCallback(%s)\n", sQuery.c_str());
			assert(m_clockPreStart > 0);
			if (m_clockPreStart == 0)
				return;
			clock_t now = clock();
			if (now - m_clockPreStart >= m_clockSpan)
			{
				assert(!sQuery.empty());
				if (AsyncOnlineQuery(sQuery))
				{
					SetOnlineQueryState(ONLINE_QUERY_STATE::ONLINE_QUERY_STATE_SEND);
				}
				else
					SetOnlineQueryState(ONLINE_QUERY_STATE::ONLINE_QUERY_STATE_ERROR);
				wprintf(L"ComboBase::OnlineQueryTimerCallback m_pOnlineQueryHost->AsyncOnlineQuery(%s)\n", sQuery.c_str());
				assert(m_weakOnlineQuery.HasUsed());
				m_weakOnlineQuery.Cancel();
			}
		}

	protected:
		virtual bool  AsyncOnlineQuery(std::wstring sQuery) = 0;

	private:
		ONLINE_QUERY_STATE m_state{ ONLINE_QUERY_STATE::ONLINE_QUERY_STATE_NONE };
		UiOnlineQueryObserver<_T>* m_observer{ nullptr };
		clock_t		m_clockPreStart{ 0 };
		clock_t		m_clockSpan{ 300 };
		nbase::WeakCallbackFlag m_weakOnlineQuery;
	};

	typedef UiOnlineQuery<std::vector<ui::kvItem>> ComboOnlineQuery;
}
